package com.whsxt.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.whsxt.constant.QueueConstant;
import com.whsxt.domain.*;
import com.whsxt.feign.OrderCartFeign;
import com.whsxt.feign.OrderMemberFeign;
import com.whsxt.feign.OrderProductFeign;
import com.whsxt.mapper.OrderItemMapper;
import com.whsxt.mapper.OrderMapper;
import com.whsxt.mapper.OrderSettlementMapper;
import com.whsxt.model.WxMsgModel;
import com.whsxt.service.OrderItemService;
import com.whsxt.service.OrderService;
import com.whsxt.utils.SnowUtil;
import com.whsxt.vo.OrderConfirmResult;
import com.whsxt.vo.OrderParam;
import com.whsxt.vo.OrderStatusResult;
import com.whsxt.vo.OrderVo;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: caoqingwen
 * @CreateTime: 2021-03-25 14:49
 * @Description: ${Description}
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {


    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private OrderItemMapper orderItemMapper;

    @Autowired
    private OrderMemberFeign orderMemberFeign;

    @Autowired
    private OrderProductFeign orderProductFeign;

    @Autowired
    private OrderCartFeign orderCartFeign;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private OrderItemService orderItemService;

    @Autowired
    private OrderSettlementMapper orderSettlementMapper;

    /**
     * 查询当前用户的订单数量
     *
     * @param openId
     * @return
     */
    @Override
    public OrderStatusResult getOrderCount(String openId) {
        OrderStatusResult result = new OrderStatusResult();
        Integer unPay = orderMapper.selectCount(new LambdaQueryWrapper<Order>()
                .eq(Order::getUserId, openId)
                .eq(Order::getStatus, 1)
        );

        Integer payed = orderMapper.selectCount(new LambdaQueryWrapper<Order>()
                .eq(Order::getUserId, openId)
                .eq(Order::getStatus, 2)
        );

        Integer consignment = orderMapper.selectCount(new LambdaQueryWrapper<Order>()
                .eq(Order::getUserId, openId)
                .eq(Order::getStatus, 3)
        );
        result.setUnPay(unPay);
        result.setPayed(payed);
        result.setConsignment(consignment);
        return result;
    }


    /**
     * 分页查询当前用户的订单
     *
     * @param page
     * @param order
     * @return
     */
    @Override
    public Page<Order> findOrderPage(Page<Order> page, Order order) {
        //查询订单
        Page<Order> orderPage = orderMapper.selectPage(page, new LambdaQueryWrapper<Order>()
                .eq(Order::getUserId, order.getUserId())
                .eq(order.getStatus() != 0, Order::getStatus, order.getStatus())
        );

        List<Order> orderList = orderPage.getRecords();
        if (CollectionUtils.isEmpty(orderList)) {
            return orderPage;
        }
        List<String> orderNumList = orderList.stream().map(Order::getOrderNumber).collect(Collectors.toList());
        //order_num 查询订单条目表
        List<OrderItem> orderItemList = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItem>()
                .in(OrderItem::getOrderNumber, orderNumList)
        );
        //组装数据
        orderList.forEach(order1 -> {
            List<OrderItem> orderItems = orderItemList
                    .stream()
                    .filter(orderItem -> orderItem.getOrderNumber().equals(order1.getOrderNumber()))
                    .collect(Collectors.toList());
            order1.setOrderItemDtos(orderItems);
        });

        return orderPage;
    }


    /**
     * 订单确认接口
     * 1、用户默认收货地址查询
     * 2、判断用户到底是从购物车进来还是直接从商品进来的
     * 3、
     *
     * @param orderParam
     * @param openId
     * @return
     */
    @Override
    public OrderConfirmResult confirmOrder(OrderParam orderParam, String openId) {
        List<Long> basketIds = orderParam.getBasketIds();
        OrderConfirmResult orderConfirmResult = new OrderConfirmResult();
        //查询用户默认收货地址
        UserAddr defaultAddr = orderMemberFeign.getDefaultAddr(openId);
        orderConfirmResult.setUserAddr(defaultAddr);

        if (CollectionUtils.isEmpty(basketIds)) {
            //从商品进来的
            orderConfirmResult = productToOrder(orderConfirmResult, orderParam, openId);
        } else {
            //从购物车进来的
            orderConfirmResult = cartToOrder(orderConfirmResult, basketIds, openId);
        }
        return orderConfirmResult;
    }


    /**
     * 从购物车进来的
     * 1、查询购物车集合
     * 2、拿到skuids
     * 3、远程调用，拿到sku集合
     * 4、循环组装数据
     *
     * @param orderConfirmResult
     * @param basketIds
     * @param openId
     * @return
     */
    private OrderConfirmResult cartToOrder(OrderConfirmResult orderConfirmResult, List<Long> basketIds, String openId) {
        //拿到购物车集合
        List<Basket> basketList = orderCartFeign.getBasketByIds(basketIds);
        if (CollectionUtils.isEmpty(basketList)) {
            return orderConfirmResult;
        }
        //拿到skuId集合
        List<Long> skuIds = basketList.stream().map(Basket::getSkuId).collect(Collectors.toList());
        //远程调用拿到sku集合
        List<Sku> skuList = orderProductFeign.getSkuByIds(skuIds);
        if (CollectionUtils.isEmpty(skuList)) {
            return orderConfirmResult;
        }

        List<OrderItem> orderItems = new ArrayList<>();
        //总金额
        List<BigDecimal> totalMoneyList = new ArrayList<>();
        //组装数据
        basketList.forEach(basket -> {
            OrderItem orderItem = new OrderItem();

            Sku sku1 = skuList.stream()
                    .filter(sku -> sku.getSkuId().equals(basket.getSkuId()))
                    .collect(Collectors.toList())
                    .get(0);
            //计算总价格
            BigDecimal price = sku1.getPrice();
            Integer count = basket.getBasketCount();
            //一个商品的总金额
            BigDecimal oneMoney = price.multiply(new BigDecimal(count));
            totalMoneyList.add(oneMoney);


            BeanUtil.copyProperties(sku1, orderItem, true);
            //有一些名字没有匹配上的
            orderItem.setProdCount(count);

            orderItems.add(orderItem);
        });


        List<OrderVo> orderVos = new ArrayList<>();
        OrderVo orderVo = new OrderVo();
        orderVo.setShopCartItemDiscounts(orderItems);
        orderVos.add(orderVo);
        orderConfirmResult.setShopCartOrders(orderVos);
        //商品总数
        Integer totalCount = basketList.stream().map(Basket::getBasketCount).reduce(Integer::sum).get();
        orderConfirmResult.setTotalCount(totalCount);
        //总金额
        BigDecimal totalMoney = totalMoneyList.stream().reduce(BigDecimal::add).get();
        orderConfirmResult.setTotal(totalMoney);
        orderConfirmResult.setActualTotal(totalMoney);


        return orderConfirmResult;
    }


    /**
     * 从商品进来的
     * 1、拿到商品id
     * 2、远程调用查询sku
     * ====可能会有优惠券
     * 3、组装数据
     *
     * @param orderConfirmResult
     * @param orderParam
     * @param openId
     * @return
     */
    private OrderConfirmResult productToOrder(OrderConfirmResult orderConfirmResult, OrderParam orderParam, String openId) {
        OrderItem orderItem = orderParam.getOrderItem();
        Long skuId = orderItem.getSkuId();
        Integer prodCount = orderItem.getProdCount();
        //远程调用，查询商品的sku,    计算价格
        List<Sku> skuList = orderProductFeign.getSkuByIds(Arrays.asList(skuId));
        if (CollectionUtils.isEmpty(skuList)) {
            //商品的信息没查到，不需要往下走了
            //throw new RuntimeException("服务器异常，请稍后再试！");
            return orderConfirmResult;
        }
        Sku sku = skuList.get(0);
        //计算价格，设置信息
        BigDecimal total = sku.getPrice().multiply(new BigDecimal(prodCount));
        //加入运费是6
        orderConfirmResult.setYunfei(new BigDecimal(6));
        orderConfirmResult.setTotal(total);
        orderConfirmResult.setActualTotal(total.add(new BigDecimal(6)));
        orderConfirmResult.setTotalCount(prodCount);

        //设置商品信息
        List<OrderVo> orderVos = new ArrayList<>();
        OrderVo orderVo = new OrderVo();
        List<OrderItem> orderItems = new ArrayList<>();
        orderItem.setPic(sku.getPic());
        orderItem.setProdName(sku.getProdName());
        orderItem.setSkuName(sku.getSkuName());
        orderItem.setPrice(sku.getPrice());
        orderItem.setSkuId(sku.getSkuId());
        orderItem.setProdId(sku.getProdId());


        orderItems.add(orderItem);
        orderVo.setShopCartItemDiscounts(orderItems);
        //每个运费都设置
        orderVo.setTransfee(new BigDecimal(6));
        orderVos.add(orderVo);
        orderConfirmResult.setShopCartOrders(orderVos);
        return orderConfirmResult;
    }


    /**
     * 订单提交
     * 1、清空购物车
     * 2、扣减mysql的库存
     * 3、扣减es的库存
     * 4、生成订单号
     * 5、写订单表
     * 6、写延迟队列
     * 7、发微信消息通知用户支付
     *
     * @param orderConfirmResult
     * @param openId
     * @return
     */
    @Override
    @Transactional
    public String orderSubmit(OrderConfirmResult orderConfirmResult, String openId) {
        //清空购物车，不能把购物车直接删除，可能从商品直接下单
        clearCart(openId, orderConfirmResult);

        //扣减mysql库存
        Map<Long, Integer> map = changeStock(orderConfirmResult);

        //扣减es库存
        changeEsStock(map);

        //生成订单号
        String orderNum = createOrderNum();

        //写订单表
        Map<String, Object> orderDetails = writerOrder(orderNum, openId, orderConfirmResult);

        //写延迟队列
        writerDeadQueue(orderNum);

        //发微信消息
        sendWxMsg(orderDetails, openId, orderNum);


        return orderNum;
    }


    /**
     * 发送微信消息
     *
     * @param orderDetails
     * @param openId
     * @param orderNum
     */
    private void sendWxMsg(Map<String, Object> orderDetails, String openId, String orderNum) {
        WxMsgModel wxMsgModel = new WxMsgModel();
        wxMsgModel.setToUser("oayvT5vsuD4TZJ4b0zNViDnDG7EA");
        wxMsgModel.setUrl("https://www.baidu.com");
        wxMsgModel.setTemplateId("Vh_fHFG0kBIeVIS5fmjd-cLIb1_bORd9LAX8fcKRwqQ");
        wxMsgModel.setTopColor("#FF0000");

        HashMap<String, Map<String, String>> data = new HashMap<>();

        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String time = format.format(new Date());

        data.put("time", WxMsgModel.buildMap(time, "#173177"));
        data.put("prodName", WxMsgModel.buildMap(orderDetails.get("prodName").toString(), "#173177"));
        data.put("price", WxMsgModel.buildMap(orderDetails.get("price").toString(), "#173177"));
        data.put("orderNum", WxMsgModel.buildMap(orderNum, "#173177"));

        wxMsgModel.setData(data);

        //放到mq
        rabbitTemplate.convertAndSend(QueueConstant.WECHAT_SEND_EX, QueueConstant.WECHAT_SEND_KEY, JSON.toJSONString(wxMsgModel));
    }


    /**
     * 写延时队列
     *
     * @param orderNum
     */
    private void writerDeadQueue(String orderNum) {
        rabbitTemplate.convertAndSend(QueueConstant.ORDER_MS_QUEUE, orderNum);
    }


    /**
     * 写订单表
     *
     * @param orderNum
     * @param openId
     * @param orderConfirmResult
     */
    private Map<String, Object> writerOrder(String orderNum, String openId, OrderConfirmResult orderConfirmResult) {
        Map<String, Object> hashMap = new HashMap<>();

        //写order（要注意金额）  order_item  order_settlement表
        //不能用前台传进来的金额，要重新计算
        //1、写order_item表
        List<OrderItem> shopCartItemDiscounts = orderConfirmResult.getShopCartOrders().get(0).getShopCartItemDiscounts();
        //拿到skuIds
        List<Long> skuIds = shopCartItemDiscounts.stream().map(OrderItem::getSkuId).collect(Collectors.toList());
        //远程调用查询sku
        List<Sku> skuList = orderProductFeign.getSkuByIds(skuIds);
        //循环计算每个商品的价格，计算所有商品的总价
        List<BigDecimal> totalMoneyList = new ArrayList<>();
        //手机订单名称
        StringBuffer stringBuffer = new StringBuffer();
        if (!CollectionUtils.isEmpty(skuList)) {
            shopCartItemDiscounts.forEach(orderItem -> {
                //计算商品的单个总价
                Integer prodCount = orderItem.getProdCount();
                //过滤条件找到对应的sku
                Sku sku1 = skuList.stream()
                        .filter(sku -> sku.getSkuId().equals(orderItem.getSkuId()))
                        .collect(Collectors.toList())
                        .get(0);
                BigDecimal price = sku1.getPrice();
                BigDecimal oneMoney = price.multiply(new BigDecimal(prodCount));

                orderItem.setPrice(price);
                orderItem.setProductTotalAmount(oneMoney);

                orderItem.setOrderNumber(orderNum);
                orderItem.setUserId(openId);
                orderItem.setRecTime(new Date());

                totalMoneyList.add(oneMoney);
                stringBuffer.append(orderItem.getProdName() + ",");
            });
        }
        orderItemService.saveBatch(shopCartItemDiscounts);

        //写order表
        Order order = new Order();
        order.setShopId(1L);
        String prodName = stringBuffer.toString().substring(0, stringBuffer.toString().lastIndexOf(","));
        order.setProdName(prodName);
        order.setUserId(openId);
        order.setOrderNumber(orderNum);
        BigDecimal totalMoney = totalMoneyList.stream().reduce(BigDecimal::add).get();
        order.setTotal(totalMoney);

        order.setActualTotal(totalMoney);
        order.setPayType(0);
        order.setRemarks("");
        order.setStatus(1);
        order.setDvyType("");
        order.setDvyId(0L);
        order.setDvyFlowId("");
        order.setFreightAmount(new BigDecimal("0"));
        order.setAddrOrderId(orderConfirmResult.getUserAddr().getAddrId());
        order.setProductNums(orderConfirmResult.getTotalCount());
        order.setCreateTime(new Date());
        order.setUpdateTime(new Date());
        order.setIsPayed(0);
        order.setDeleteStatus(0);
        order.setRefundSts(0);
        order.setReduceAmount(new BigDecimal("0"));
        order.setOrderType((byte) 0);
        order.setCloseType(0);
        orderMapper.insert(order);

        //写订单结算表
        OrderSettlement orderSettlement = new OrderSettlement();
        orderSettlement.setOrderNumber(orderNum);
        orderSettlement.setIsClearing(0);
        orderSettlement.setUserId(openId);
        orderSettlement.setCreateTime(new Date());
        orderSettlement.setVersion(0);
        orderSettlement.setPayStatus(0);
        orderSettlementMapper.insert(orderSettlement);

        hashMap.put("price", totalMoney);
        hashMap.put("prodName", prodName);
        return hashMap;
    }


    /**
     * 生成一个订单号
     *
     * @return
     */
    private String createOrderNum() {
        return SnowUtil.snowflake.nextIdStr();
    }


    /**
     * 扣减es的库存
     * 异步的方式， mq 就是商品的快速导入
     *
     * @param map
     */
    private void changeEsStock(Map<Long, Integer> map) {

        rabbitTemplate.convertAndSend(QueueConstant.PROD_CHANGE_EX, QueueConstant.PROD_CHANGE_KEY, JSON.toJSONString(map));

    }


    /**
     * 扣减mysql库存
     *
     * @param orderConfirmResult
     * @return
     */
    private Map<Long, Integer> changeStock(OrderConfirmResult orderConfirmResult) {
        //扣减2个表  prod   sku         Map<"prod",Map<Long,Integer>>      Map<"sku",Map<Long,Integer>>
        Map<String, Map<Long, Integer>> data = new HashMap<>();

        Map<Long, Integer> prodMap = new HashMap<>();
        Map<Long, Integer> skuMap = new HashMap<>();
        //组装数据
        List<OrderItem> shopCartItemDiscounts = orderConfirmResult.getShopCartOrders().get(0).getShopCartItemDiscounts();
        shopCartItemDiscounts.forEach(orderItem -> {
            Long prodId = orderItem.getProdId();
            Long skuId = orderItem.getSkuId();
            Integer prodCount = orderItem.getProdCount() * -1;

            if (prodMap.containsKey(prodId)) {
                int count = prodMap.get(prodId) + prodCount;
                prodMap.put(prodId, count);
            } else {
                prodMap.put(prodId, prodCount);
            }
            skuMap.put(skuId, prodCount);
        });

        data.put("prod", prodMap);
        data.put("sku", skuMap);

        //远程调用减库存
        orderProductFeign.changeStock(data);

        return prodMap;

    }


    /**
     * 清空购物车，不能把购物车直接删除，可能从商品直接下单
     *
     * @param openId
     * @param orderConfirmResult
     */
    private void clearCart(String openId, OrderConfirmResult orderConfirmResult) {

        OrderVo orderVo = orderConfirmResult.getShopCartOrders().get(0);
        List<OrderItem> shopCartItemDiscounts = orderVo.getShopCartItemDiscounts();
        List<Long> skuIds = shopCartItemDiscounts
                .stream()
                .map(OrderItem::getSkuId)
                .collect(Collectors.toList());

        //远程调用清空购物车
        orderCartFeign.cleanCart(openId, skuIds);
    }


}
